#pragma once
#include "vector.h"
#include "matrix.h"
#include "scenenode.h"


/**
 * Klasa kamery.
 *
 * @author Krzysztof Klein
 * @version 0.1
 */
class Camera
{
	/**
	 * Wezel sceny do ktorego jest przyczepiona kamera
	 */
	const SceneNode* refNode;

	/**
	 * Czas animacji kamery.
	 * -1 = brak animacji, 0 = poczatek, ..., max = koniec
	 */
	int animationTime;

	/**
	 * Macierz transformacji poczatku animacji
	 */
	Matrix animationBeginTransformation;

public:

	/**
	 * Tryby kamery
	 */
	enum Mode
	{
		// Standardowa kamera
		Normal,

		// Przyblizenie
		CloseUp,

		// Widok z gory
		SkyCamera
	};

	/**
	 * Kierunek patrzenia kamery
	 */
	enum Direction
	{
		// +Z
		North,

		// +X
		East,

		// -Z
		South,

		// -X
		West
	};

private:

	/**
	 * Aktualny tryb kamery
	 */
	Mode mode;

	/**
	 * Aktualny kierunek kamery
	 */
	Direction direction;

public:

	/**
	 * Aktualny tryb kamery
	 */
	Mode getMode() const { return mode; }
	
	/**
	 * Aktualny kierunek kamery
	 */
	Direction getDirection() const { return direction; }


	/**
	 * Konstruktor domyslny.
	 */
	Camera() : refNode(NULL), mode(Normal), direction(North), animationTime(-1) { }

	/**
	 * Wezel sceny do ktorego jest przyczepiona kamera
	 */
	const SceneNode* getReferenceNode() const { return refNode; }
	void setReferenceNode(const SceneNode* node) { refNode = node; }

	/**
	 * Zwraca macierz widoku na podstawie trybu kamery i kierunku
	 */
	Matrix getTransformationByMode(Mode mode, Direction direction) const;

	/**
	 * Zwraca macierz widoku na podstawie trybu kamery i klatki animacji
	 */
	Matrix getAnimatedTransformation();

	/**
	 * Rozpoczyna plynne przejscie kamery
	 */
	void switchToMode(Mode m, Direction d);

	/**
	 * Inkrementuje klatke animacji kamery
	 */
	void animationStep();

	/**
	 * Resetuje kamere.
	 * Zatrzymuje animacje i ustawia standardowy tryb.
	 */
	void reset() { animationTime = -1; mode = Normal; direction = North; }

	/**
	 * Zwraca wektor jednostkowy wskazujacy kierunek 'na wprost'.
	 * Wektor ten zalezy tylko od kierunku kamery.
	 */
	Vector getForwardVector() const;

	/**
	 * Zwraca wektor jednostkowy wskazujacy kierunek 'na prawo'.
	 * Wektor ten zalezy tylko od kierunku kamery.
	 */
	Vector getRightTurnVector() const;

};